﻿using System;
using System.ComponentModel;
using System.Collections.Generic;

using System.Threading;

using System.Windows;
using System.Windows.Controls;

using System.Windows.Input;
using System.Windows.Navigation;
using System.Windows.Media.Animation;

using EagleJournal.Controls;
using EagleJournal.Components;

using EagleJournalBE.Util;
using EagleJournalBE.Database.Tables;

namespace EagleJournal
{
    public struct POInformation
    {
        public int      ID;
        public string   Description;
        public float    Amount;
        public string   Deadline;
    }

    public struct PODeadline
    {
        public long     Time;
    }

	public partial class ScreenOrder : UserControl
    {
        public static readonly  RoutedEvent
            InvokeBackButtonEvent           = EventManager.RegisterRoutedEvent("InvokeBackButton", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(ScreenOrder));
        public event            RoutedEventHandler
            InvokeBackButton
        {
            add     { this.AddHandler(InvokeBackButtonEvent, value); }
            remove  { this.RemoveHandler(InvokeBackButtonEvent, value); }
        }

        public static readonly  RoutedEvent
            InvokeHelpButtonClickedEvent    = EventManager.RegisterRoutedEvent("InvokeHelpButtonClicked", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(ScreenOrder));
        public event            RoutedEventHandler
            InvokeHelpButtonClicked
        {
            add     { this.AddHandler(InvokeHelpButtonClickedEvent, value); }
            remove  { this.RemoveHandler(InvokeHelpButtonClickedEvent, value); }
        }

        bool                    dataLoaded                          = false;

        Storyboard              showDimmer;
        Storyboard              hideDimmer;

        Storyboard              showViewClient;
        Storyboard              hideViewClient;

        Storyboard              showAffectedClients;
        Storyboard              hideAffectedClients;

        TableClient             clients;
        TableClientAffected     affectedClients;


        TableDeadline           deadlines;
        TablePurchaseOrder      purchaseOrders;

		public                  ScreenOrder                         ()
		{
			this.InitializeComponent();
		}

        public override void    OnApplyTemplate                     ()
        {
            base.OnApplyTemplate();

            showDimmer      = (Storyboard)this.FindResource("ShowDimmer");
            hideDimmer      = (Storyboard)this.FindResource("HideDimmer");

            showViewClient = (Storyboard)this.FindResource("ShowViewClient");
            hideViewClient = (Storyboard)this.FindResource("HideViewClient");
            hideViewClient.Completed += new EventHandler((o, sbe) =>
            {
                this.RootGrid.Children.Remove(this.EditClient);
            });

            showAffectedClients = (Storyboard)this.FindResource("ShowAffectedClients");
            hideAffectedClients = (Storyboard)this.FindResource("HideAffectedClients");
            hideAffectedClients.Completed += new EventHandler((o, sbe) =>
            {
                this.RootGrid.Children.Remove(this.ViewClient);
            });

            showDimmer.Freeze();
            hideDimmer.Freeze();
        }

        private         void    UserControl_Loaded                  (object sender, RoutedEventArgs e)
        {
            if (!dataLoaded)
            {
                LoadData(string.Empty);

                dataLoaded = true;

                this.RootGrid.Children.Remove(this.EditClient);
            }

            this.Data.SelectedIndex = -1;
        }

        private         void    ButtonOrderAdd_Click                (object sender, RoutedEventArgs e)
        {
            this.Data.SelectedIndex = -1;

            this.OrderEdit.AffectedClients  = null;
            this.EditClient.AffectedClients = null;

            this.OrderEdit.ClearData();
            this.OrderEdit.CreateMode = true;

            this.TextClientInfo.Text = "Create purchase order";

            VisualStateManager.GoToState(this, "Editing", false);
        }

        private         void    ButtonBack_Click                    (object sender, RoutedEventArgs e)
        {
            this.RaiseEvent(new RoutedEventArgs(InvokeBackButtonEvent));
        }
        private         void    ButtonSort_Click                    (object sender, RoutedEventArgs e)
        {
            if (this.BorderSort.Visibility == Visibility.Collapsed)
                this.BorderSort.Visibility = Visibility.Visible;
            else
                this.BorderSort.Visibility = Visibility.Collapsed;
        }
        private         void    ButtonHelp_Click                    (object sender, RoutedEventArgs e)
        {
            this.RaiseEvent(new RoutedEventArgs(InvokeHelpButtonClickedEvent));
        }

        private         void    Data_SelectionChanged               (object sender, SelectionChangedEventArgs e)
        {
            if (this.Data.SelectedIndex != -1)
            {
                ListPOInfo orders = this.Data.SelectedItem as ListPOInfo;

                if (orders != null)
                {
                    this.OrderInfo.IsEnabled = true;

                    List<object> row = this.purchaseOrders.TableData[this.Data.SelectedIndex];

                    PODeadline deadline = new PODeadline();
                    foreach (List<object> drow in this.deadlines.TableData)
                    {
                        if ((int)drow[0] == (int)row[1])
                        {
                            deadline = new PODeadline()
                            {
                                Time = (long)Convert.ToInt64(drow[1])
                            };

                            break;
                        }
                    }

                    this.OrderInfo.ClearData();
                    this.OrderInfo.PassData(
                        (int)row[0], 
                        new POPanelInfo() { 
                            ID          = Convert.ToString(row[2] is System.DBNull ? 0 : (int)row[2]),
                            Amount      = Convert.ToString((float)row[3]), 
                            Company     = (string)row[4],
                            Deadline    = DateTime.FromBinary(deadline.Time).ToLongDateString(),
                            Description = (string)row[5]
                        }
                    );
                }
            }
            else
            {
                this.OrderInfo.IsEnabled = false;
                this.OrderInfo.ClearData();
            }
        }

        private         void    ViewClient_InvokeDialogConfirm      (object sender, RoutedEventArgs e)
        {
            this.OrderEdit.AffectedClients = this.EditClient.AffectedClients;

            this.BeginStoryboard(hideViewClient);
            this.BeginStoryboard(hideDimmer);
        }
        private         void    ViewClient_InvokeDialogConfirm_1    (object sender, RoutedEventArgs e)
        {
            this.BeginStoryboard(hideDimmer);
            this.BeginStoryboard(hideAffectedClients);
        }

        private         void    PanelOrderInfo_InvokeOrderEdit      (object sender, RoutedEventArgs e)
        {
            this.OrderEdit.CreateMode = false;
            this.TextClientInfo.Text = "Edit purchase order";

            // get PO deadline
            List<object> poRow = this.purchaseOrders.TableData[this.Data.SelectedIndex];

            PODeadline deadline = new PODeadline();
            foreach (List<object> drow in this.deadlines.TableData)
            {
                if ((int)drow[0] == (int)poRow[1])
                {
                    deadline = new PODeadline()
                    {
                        Time = (long)Convert.ToInt64(drow[1])
                    };

                    break;
                }
            }

            // then pass the data
            this.OrderEdit.ClearData();
            this.OrderEdit.PassData((int)this.purchaseOrders.TableData[this.Data.SelectedIndex][0], (int)poRow[0], 
                new POPanelEdit()
                {
                    Deadline    = deadline.Time,
                    ID          = Convert.ToString(poRow[2]),
                    Amount      = Convert.ToString(poRow[3]),
                    Company     = (string)poRow[4],
                    Description = (string)poRow[5],
                });

            VisualStateManager.GoToState(this, "Editing", false);
        }
        private         void    PanelOrderInfo_InvokeOrderClients   (object sender, RoutedEventArgs e)
        {
            if (!this.RootGrid.Children.Contains(this.ViewClient))
                this.RootGrid.Children.Add(this.ViewClient);

            List<ClientInformation> clients = new List<ClientInformation>();
            
            this.affectedClients.Filter("POID = " + this.purchaseOrders.TableData[this.Data.SelectedIndex][0]);
            foreach (List<object> row in this.affectedClients.TableData)
            {
                foreach (List<object> client in this.clients.TableData)
                {
                    if ((int)row[1] == (int)client[0])
                    {
                        clients.Add(new ClientInformation()
                        {
                            ID              = (int)     client[0],
                            Name            = (string)  client[1],
                            Notifications   = 0,
                        });

                        break;
                    }
                }
            }

            this.ViewClient.ClearData();
            this.ViewClient.PassData(clients);

            this.BeginStoryboard(showDimmer);
            this.BeginStoryboard(showAffectedClients);
        }

        private         void    OrderEdit_InvokeEditClient          (object sender, RoutedEventArgs e)
        {
            if (!this.RootGrid.Children.Contains(this.EditClient))
                this.RootGrid.Children.Add(this.EditClient);

            this.EditClient.ClearData   ();
            this.EditClient.PassData    (this.OrderEdit.AffectedClients);

            this.BeginStoryboard(this.showDimmer);
            this.BeginStoryboard(this.showViewClient);
        }
        private         void    OrderEdit_InvokeEditComplete        (object sender, RoutedEventArgs e)
        {
            this.TextClientInfo.Text = "Purchase orders";

            this.OrderInfo.ClearData();
            this.OrderEdit.ClearData();

            VisualStateManager.GoToState(this, "Normal", false);

            LoadData(string.Empty);
        }

        private         void    LoadData                            (string filter)
        {
            if (DesignerProperties.GetIsInDesignMode(this))
                return;

            BackgroundWorker bWorker = new BackgroundWorker();
            bWorker.WorkerReportsProgress = true;

            bWorker.DoWork += new DoWorkEventHandler((o, dwa) =>
            {
                Logger.WriteInfo(LoggingType.INFO, this, "Loading purchase orders list...");

                try
                {
                    dataLoaded = false;

                    Dispatcher.Invoke(new Action(() => { this.Data.Items.Clear(); }), null);

                    if (purchaseOrders == null)
                        purchaseOrders = new TablePurchaseOrder();

                    if (deadlines == null)
                        deadlines = new TableDeadline();

                    if (clients == null)
                        clients = new TableClient();

                    if (affectedClients == null)
                        affectedClients = new TableClientAffected();

                    clients.Refresh();
                    affectedClients.Refresh();

                    deadlines.Refresh();
                    purchaseOrders.Refresh();

                    this.OrderEdit.LinkPOTable(purchaseOrders, deadlines, clients, affectedClients);

                    if (!string.IsNullOrEmpty(filter))
                        Dispatcher.Invoke(new Action(() => { this.purchaseOrders.Filter("description LIKE '%" + this.TextSearch.Text + "%'"); }), null);

                    int i = 0;
                    foreach (List<object> row in purchaseOrders.TableData)
                    {
                        PODeadline deadline = new PODeadline();
                        foreach (List<object> drow in this.deadlines.TableData)
                        {
                            if ((int)drow[0] == (int)row[1])
                            {
                                deadline = new PODeadline()
                                {
                                    Time = (long)Convert.ToInt64(drow[1])
                                };

                                break;
                            }
                        }

                        POInformation po = new POInformation()
                        {
                            Description = (string)row[5],
                            Amount = (float)row[3],
                            Deadline = DateTime.FromBinary(deadline.Time).ToLongDateString(),
                            ID = (int)row[0],
                        };

                        bWorker.ReportProgress((int)((i++ / (float)this.purchaseOrders.TableData.Count) * 100), po);

                        Thread.Sleep(10);
                    }
                }
                catch (Exception ex)
                {
                    EagleMessageBox.ShowMessageBox("Purchase Orders load", "Cannot load purchase orders list!", MessageBoxImage.Error, MessageBoxButton.OK);

                    Logger.WriteInfo(LoggingType.WARN, this, "Cannot load PO list!");
                    Logger.WriteInfo(LoggingType.STOP, this, ex.ToString());
                }
            });
            bWorker.ProgressChanged += new ProgressChangedEventHandler((o, rpce) =>
            {
                POInformation poInfo = (POInformation)rpce.UserState;

                ListPOInfo info = new ListPOInfo()
                {
                    Content     = poInfo.Description,
                    PODeadline  = poInfo.Deadline,
                    POSerialID  = Convert.ToString(Math.Round(poInfo.Amount, 2)), 
                    POID        = poInfo.ID,
                };

                this.Data.Items.Add(info);
            });
            bWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler((o, rwce) =>
            {
                Logger.WriteInfo(LoggingType.INFO, this, "Purchase orders load complete!");

                VisualStateManager.GoToState(this, "Normal", false);
                dataLoaded = true;
            });
            bWorker.RunWorkerAsync();
        }

        private         void    TextSearch_TextChanged              (object sender, TextChangedEventArgs e)
        {
            if (this.TextSearch.Text.Length > 0)
            {
                this.TextClientInfo.Text = "Search results";

                LoadData(this.TextClientInfo.Text);
            }
            else
            {
                this.TextClientInfo.Text = "Purchase Orders";

                LoadData(string.Empty);
            }
        }
	}
}
